home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2MISC / CSDPMI1S.ZIP / SRC / CWSDPMI / MSWITCH.ASM < prev    next >
Encoding:
Assembly Source File  |  1995-12-01  |  10.4 KB  |  515 lines

  1. ; Copyright (C) 1995 CW Sandmann (sandmann@clio.rice.edu) 102 Hurst Ct, Destrehan, LA 70047
  2. ; Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. ;
  4. ; This file is distributed under the terms listed in the document
  5. ; "copying.cws", available from CW Sandmann at the address above.
  6. ; A copy of "copying.cws" should accompany this file; if not, a copy
  7. ; should be available from where this file was obtained.  This file
  8. ; may not be distributed without a verbatim copy of "copying.cws".
  9. ;
  10. ; This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12.  
  13. ; Modified for VCPI Implement by Y.Shibata Aug 5th 1991
  14.  
  15.     title    switch between real and protected mode
  16.     include segdefs.inc
  17.     include tss.inc
  18.     include gdt.inc
  19.     include vcpi.inc
  20.  
  21. ;------------------------------------------------------------------------
  22.  
  23.     start_data16
  24.  
  25.     extrn    _gdt:gdt_s
  26.     extrn    _gdt_phys:gdt_s
  27.     extrn    _idt_phys:gdt_s
  28.     extrn    _tss_ptr:word
  29.     extrn    _use_xms:byte
  30.     extrn    _hard_master_lo:byte
  31.     extrn    _hard_master_hi:byte
  32.     extrn    _hard_slave_lo:byte
  33.     extrn    _hard_slave_hi:byte
  34.     extrn    _mtype:byte
  35.  
  36.     extrn    _vcpi_installed:byte    ;VCPI Installed set this not Zero
  37.     extrn    _vcpi_entry:fword
  38.     extrn    _abs_client:dword
  39.     extrn    _DPMIsp:word
  40.     extrn    _saved_interrupt_vector:dword
  41.  
  42.     end_data16
  43.     start_bss
  44.  
  45.     public    _dr
  46. _dr    label    dword
  47. _dr0    dd    ?
  48. _dr1    dd    ?
  49. _dr2    dd    ?
  50. _dr3    dd    ?
  51.     dd    ?
  52.     dd    ?
  53. _dr6    dd    ?
  54. _dr7    dd    ?
  55.  
  56.     public    _c_tss, _a_tss, _o_tss, _f_tss
  57. _c_tss    label    tss_s    ; for "real mode" state
  58.     db    type tss_s dup (?)
  59. _a_tss    label    tss_s    ; for running program
  60.     db    type tss_s dup (?)
  61. _o_tss    label    tss_s    ; for convenience functions
  62.     db    type tss_s dup (?)
  63. _f_tss    label    tss_s    ; for page handling
  64.     db    type tss_s dup (?)
  65.  
  66.     public    _was_exception
  67. _was_exception    db    ?        ; exceptions set this to 1
  68.  
  69.     end_bss
  70.  
  71. ;------------------------------------------------------------------------
  72.  
  73.     start_code16
  74.  
  75.     extrn    _xms_local_enable_a20:near
  76.     extrn    _xms_local_disable_a20:near
  77.  
  78. real_stack    dd    ?
  79. real_idt    dw    03ffh, 0000h, 0000h
  80.  
  81.     public    _go32
  82. _go32    proc    near
  83.     push    si
  84.     push    di
  85.     push    bx
  86. _go32_1:
  87. ;    push    0b000h                ;dbg
  88. ;    pop    fs                ;dbg
  89. ;    mov    word ptr fs:[0f01h],07h        ;dbg - normal
  90.     mov    ax,DGROUP            ; Compute physical offset
  91.     xor    dx,dx                ; of tss_ptr
  92.     shld    dx,ax,4                ; Seg * 16
  93.     shl    ax,4
  94.     add    ax,_tss_ptr            ; plus tss_ptr
  95.     adc    dx,0
  96.     mov    _gdt[g_atss].base0,ax            ; Trick here - make atss
  97.     mov    _gdt[g_atss].base1,dl            ; selector point to
  98.     mov    _gdt[g_atss].base2,dh            ; tss_ptr (jmpt g_atss)
  99.  
  100.  
  101.     mov    al,0fdh                    ; clear busy flag
  102.     and    byte ptr _gdt[g_atss].stype,al
  103.     and    byte ptr _gdt[g_ctss].stype,al        ; non-VCPI LDTR below
  104.  
  105.     mov    _was_exception,0
  106.  
  107. ; set real_stack for return from _go32
  108.     mov    word ptr cs:real_stack,sp
  109.     mov    word ptr cs:real_stack+2,ss
  110.     movzx    esp,sp                ; make sure it's OK
  111.  
  112.     cli
  113.  
  114.     call    set_a20
  115.     cmp    _vcpi_installed,0
  116.     je    short real_to_protect        ;Not VCPI Mode
  117.     mov    esi,_abs_client
  118.     mov    ax,VCPI_MODE_CHANGE
  119.     int    VCPI_REQ            ;Change Protect Mode
  120. ;end_loop0:
  121. ;    jmp    short end_loop0            ;Never Come here!! Safety Loop
  122.  
  123. real_to_protect:
  124.     or    _gdt[g_rdata].lim1,40h        ;Set the big bit (non-vcpi only)
  125.     lgdt    fword ptr _gdt_phys
  126.     lidt    fword ptr _idt_phys
  127.  
  128.     mov    eax,cr0
  129.     or    al,1
  130.     mov    cr0,eax                ; we're in protected mode!
  131.     db    0eah                ; far jmp
  132.     dw    offset go_protect_far_jump
  133.     dw    g_rcode
  134. ;
  135. ;    Entry Protect Mode
  136. ;
  137.     public    _protect_entry
  138. _protect_entry    label    near
  139.  
  140. go_protect_far_jump:
  141.     cli
  142.     mov    ax,g_rdata
  143.     mov    ds,ax
  144.     mov    es,ax
  145.     mov    fs,ax
  146.     mov    gs,ax
  147.     mov    ss,ax
  148.     mov    sp,word ptr cs:real_stack    ;Need VCPI Inialize
  149.     xor    eax,eax
  150.     mov    cr2,eax         ;zero so we can tell INT 0E from page fault
  151.  
  152.     mov    eax,_dr0
  153.     mov    dr0,eax
  154.     mov    eax,_dr1
  155.     mov    dr1,eax
  156.     mov    eax,_dr2
  157.     mov    dr2,eax
  158.     mov    eax,_dr3
  159.     mov    dr3,eax
  160.     mov    eax,_dr7
  161.     mov    dr7,eax
  162.  
  163.     cmp    _vcpi_installed,0
  164.     jne    short no_tss_load        ;Now Paging Mode in VCPI
  165.     mov    bx,_tss_ptr
  166.     mov    eax,[bx].tss_cr3
  167.     or    eax,eax                ;Test for zero
  168.     je    short set_paging_far_jump
  169.     mov    cr3,eax
  170.     mov    eax,cr0
  171.     or    eax,80000000h
  172.     mov    cr0,eax                ; paging enabled!
  173.     db    0eah                ; far jmp
  174.     dw    offset set_paging_far_jump
  175.     dw    g_rcode
  176. set_paging_far_jump:
  177.     mov    ax,g_ctss
  178.     ltr    ax
  179. no_tss_load:
  180.     jmpt    g_atss                ; load state from VCPU
  181.  
  182. _go32    endp
  183.  
  184. ; _go_real_mode must follow the task jump, so a task jump to return
  185. ; is valid
  186.  
  187.     public    _go_real_mode
  188. _go_real_mode    proc    near
  189.  
  190.     mov    eax,dr6
  191.     mov    _dr6,eax
  192.  
  193.     cmp    _vcpi_installed,0
  194.     je    short protect_to_real
  195.  
  196. ;Make VCPI call to return to real
  197.     clts                ;TS Clear
  198.     mov    eax,DGROUP
  199.     push    eax            ;GS
  200.     push    eax            ;FS
  201.     push    eax            ;DS
  202.     push    eax            ;ES
  203.     push    eax            ;SS
  204.     movzx    eax,word ptr cs:real_stack
  205.     push    eax            ;ESP
  206.     pushfd                ;EFLAGS
  207.     mov    ax,_TEXT        ;high word still zero
  208.     push    eax            ;CS
  209.     mov    ax,offset back_to_v86    ;high word still zero
  210.     push    eax            ;EIP
  211.     movzx    esp,sp
  212.  
  213.     mov    ax,g_core
  214.     mov    ds,ax
  215.     mov    ax,VCPI_MODE_CHANGE
  216.     assume    es:DGROUP
  217.     call    fword ptr es:_vcpi_entry
  218. ;end_loop1:
  219. ;    jmp    short end_loop1        ;Never Come here!! Safety Loop
  220.  
  221. protect_to_real:
  222.     and    _gdt[g_rdata].lim1,0bfh        ;Clear the big bit (non-vcpi only)
  223.     push    ss
  224.     pop    ss                ;Reload
  225.     mov    eax,cr0
  226.     and    eax,07ffffff6h ; clear PE, TS, PG
  227.     mov    cr0,eax
  228.  
  229.     db    0eah                ; far jmp
  230.     dw    offset back_to_real_far_jump
  231.     dw    _TEXT
  232. ;
  233. ;    Entry Real Mode
  234. ;
  235. back_to_real_far_jump:
  236.  
  237.     lidt    fword ptr cs:real_idt
  238.     lss    sp,cs:real_stack
  239. back_to_v86:
  240.  
  241.     mov    ax,ss
  242.     mov    ds,ax
  243.     mov    es,ax
  244.     mov    fs,ax
  245.     mov    gs,ax
  246.  
  247. ;    call    _reset_a20
  248.  
  249.     cmp    _was_exception,0
  250.     je    short not_hard
  251.  
  252.     mov    bx,_tss_ptr
  253.     mov    al,[bx].tss_irqn
  254.  
  255. ;    push    0b000h                ;dbg
  256. ;    pop    fs                ;dbg
  257. ;    mov    ah, 70h                ;dbg - reverse
  258. ;    mov    word ptr fs:[0f00h],ax        ;dbg
  259.  
  260.     mov    bx,16                ;pseudo IRQ
  261.     cmp    al,1ch
  262.     je    short is_hard_1
  263.     xor    bx,bx                ;IRQ base
  264.     cmp    al,_hard_master_lo
  265.     jb    short try_slavepic
  266.     cmp    al,_hard_master_hi
  267.     jbe    short is_hard
  268. try_slavepic:
  269.     mov    bl,8                ;IRQ base
  270.     cmp    al,_hard_slave_lo
  271.     jb    short not_hard
  272.     cmp    al,_hard_slave_hi
  273.     ja    short not_hard
  274.  
  275. is_hard:
  276. ;    mov    cl,_hard_slave_lo
  277. ;    add    cl,5
  278. ;    cmp    al,cl
  279. ;    je    short not_hard        ; for NPX errors
  280.  
  281. ;    mov    cl,_hard_master_lo
  282. ;    inc    cl
  283. ;    cmp    al,cl
  284. ;    je    short not_hard        ; to check for ^C
  285.  
  286.     mov    ah,al
  287.     and    ah,7            ; IRQ offset
  288.     add    bl,ah            ; IRQ #
  289. is_hard_1:
  290.     shl    bx,2
  291.     add    bx,offset _saved_interrupt_vector    ;ES is already DS
  292.     cmp    word ptr [bx+2],0
  293.     jne    short redirect
  294.  
  295.     push    0            ; Not redirected, use interrupt table
  296.     pop    es
  297.     movzx    bx,al
  298.     shl    bx,2            ; 4 bytes per interrupt entry
  299. redirect:
  300.     push    _DPMIsp            ; Needed for RMCB's to be recursive
  301.     mov    _DPMIsp,sp
  302.     sub    _DPMIsp,spare_stack
  303.     push    3002h
  304.     call    dword ptr es:[bx]        ; Really an interrupt
  305.     pop    _DPMIsp
  306.     jmp    _go32_1
  307.  
  308. not_hard:
  309.     pop    bx
  310.     pop    di
  311.     pop    si
  312.     ret
  313.  
  314. _go_real_mode    endp
  315.  
  316. ;------------------------------------------------------------------------
  317.     public    _reset_a20
  318. _reset_a20    proc    near
  319.     cmp    _vcpi_installed,0
  320.     jne    short reset_a20_nop
  321.     cmp    _use_xms,0
  322.     je    short reset_a20_local
  323.     call    _xms_local_disable_a20
  324. reset_a20_nop:
  325.     ret
  326.  
  327. reset_a20_local:
  328.     cmp    _mtype,0    ; PC98 raw mode (640K only)
  329.     jne    short reset_a20_nop
  330.     in    al,092h        ; 092h is the system control port "A"
  331.                 ; for PS/2 models
  332.     and    al,not 2    ; this resets the A20 bit in register al
  333.     jmp    SHORT $+2    ; forget the instruction fetch
  334.     out    092h,al        ; set the A20 bit off
  335.     ret
  336. _reset_a20    endp
  337.  
  338. set_a20 proc    near
  339.     cmp    _vcpi_installed,0
  340.     jne    short set_a20_nop
  341.     cmp    _use_xms,0
  342.     je    short set_a20_local
  343.     call    _xms_local_enable_a20
  344. set_a20_nop:
  345.     ret
  346.  
  347. set_a20_local:
  348.     cmp    _mtype,0
  349.     jne    short set_a20_nop
  350.     pushf
  351.     cli
  352.     in    al,092h        ; 092h is the system control port "A"
  353.                 ; for PS/2 models
  354.     or    al,2        ; this sets the A20 bit in register al
  355.     jmp    SHORT $+2    ; forget the instruction fetch
  356.     out    092h,al        ; set the A20 bit on
  357.  
  358.     xor    ax,ax        ; zero it
  359.     mov    fs,ax
  360.     dec    ax        ; ax = 0ffffh
  361.     mov    gs,ax
  362.     mov    bx,fs:[0]
  363.     mov    word ptr fs:[0],1234
  364.     cmp    word ptr gs:[16],1234
  365.     je    short need_to_set_a20
  366.     mov    word ptr fs:[0],4321
  367.     cmp    word ptr gs:[16],4321
  368.     je    short need_to_set_a20
  369.     mov    fs:[0],bx
  370.     popf
  371.     ret
  372.  
  373. need_to_set_a20:
  374.     mov    fs:[0],bx
  375.     call    waitkb
  376.     mov    al,0d1h
  377.     out    64h,al
  378.     call    waitkb
  379.     mov    al,0dfh        ; Patrick
  380.     out    60h,al
  381.     call    waitkb
  382.     mov    al,0ffh        ; Patrick
  383.     out    64h,al        ; Patrick
  384.     call    waitkb        ; Patrick
  385.     xor    ax,ax        ; zero it
  386.     mov    fs,ax
  387.     dec    ax        ; ax = 0ffffh
  388.     mov    gs,ax
  389.     mov    bx,fs:[0]
  390.  
  391. wait_for_valid_a20:
  392.     mov    word ptr fs:[0],1234
  393.     cmp    word ptr gs:[16],1234
  394.     je    wait_for_valid_a20
  395.     mov    word ptr fs:[0],4321
  396.     cmp    word ptr gs:[16],4321
  397.     je    wait_for_valid_a20
  398.  
  399.     mov    fs:[0],bx
  400.     popf
  401.     ret
  402.  
  403. waitkb:
  404.     xor    cx,cx        ; zero it
  405. waitkb1:
  406.     in    al,64h
  407.     test    al,2
  408.     loopnz    waitkb1
  409.     je    short waitkb3
  410. waitkb2:
  411.     in    al,64h
  412.     test    al,2
  413.     loopnz    waitkb1
  414. waitkb3:
  415.     ret
  416. set_a20 endp
  417.  
  418. ;------------------------------------------------------------------------
  419.  
  420.     public    _cpumode    ; 0=real mode, 1=V86
  421. _cpumode:
  422.     smsw    ax
  423.     and    ax,1
  424.     ret
  425.  
  426. ;------------------------------------------------------------------------
  427. ; Determination of Cpu type.  EAX, EBX, ECX, EDX destroyed.
  428. ;    0  for 8086/80186
  429. ;    2  for 80286
  430. ;    3  for 386
  431. ;    4  for 486
  432. ;    5  for 586 (Pentium) or better (thanks, Morten!)
  433.  
  434. cpuid    macro
  435.     db    0fh,0a2h
  436.     endm
  437.  
  438.     public    _cputype    ; from Intel 80486 reference manual
  439. _cputype:
  440.     xor    cx,cx        ; default type is 8086
  441.     pushf
  442.     pop    bx
  443.     and    bh,0fh
  444.     push    bx
  445.     popf
  446.     pushf
  447.     pop    ax
  448.     and    ax,0f000h
  449.     cmp    ax,0f000h
  450.     jz    short cpu8086
  451.     or    bh,0f0h
  452.     push    bx
  453.     popf
  454.     pushf
  455.     pop    ax
  456.     and    ax,0f000h
  457.     jz    short cpu286
  458.  
  459.     mov    dx,sp        ; Save old SP
  460.     and    sp,not 3    ; Align it! (we will set AC flag)
  461.     mov    al,18        ; AC flag number
  462.     call    cpuflipflag
  463.     mov    sp,dx
  464.     jnc    short cpu386
  465.     mov    al,21        ; ID flag number
  466.     call    cpuflipflag
  467.     jnc    short cpu486
  468.  
  469. ;The cpu supports the CPUID instruction.  Maybe Pentium or late 486?
  470.     xor    eax,eax
  471.     cpuid            ; ebx:edx:ecx = vendor id; eax = max support
  472.     or    eax,eax
  473.     mov    al,5
  474.     jz    short cpu_pentium
  475.     xor    eax,eax
  476.     inc    ax        ; call with eax = 1
  477.     cpuid            ; edx=features; ah&0f = family; al=model/step
  478.     mov    al,ah
  479. cpu_pentium:
  480.     and    ax,0fh
  481.     ret    
  482. cpu486:
  483.     inc    cx
  484. cpu386:
  485.     inc    cx
  486. cpu286:
  487.     inc    cx
  488.     inc    cx
  489. cpu8086:                ; or 186
  490.     mov    ax,cx
  491.     ret
  492.  
  493. cpuflipflag:        ; Try to flip flag #Al in Eflags, Return C=1 if possible
  494.     push    si    ; This plus the pushed ret address still stack aligned
  495.     movzx    esi,al
  496.     pushfd
  497.     pop    eax
  498.     mov    ebx,eax
  499.     btc    eax,esi
  500.     push    eax
  501.     popfd
  502.     pushfd
  503.     pop    eax
  504.     xor    eax,ebx
  505.     push    ebx
  506.     popfd
  507.     bt    eax,esi
  508.     pop    si
  509.     ret
  510. ;------------------------------------------------------------------------
  511.  
  512.     end_code16
  513.  
  514.     end
  515.